// // ******************************************************************
// //       /\ /|       @file       TranslationRecordCommandHandler.cs
// //       \ V/        @brief      await29
// //       | "")       @author     Await, 285283010@qq.com
// //       /  |
// //      /  \\        @Modified   2025-03-01 21:03
// //    *(__\_\        @Copyright  Copyright (c) , 2025-02-23 10:02 Await
// // ******************************************************************

using AutomaticSubtitles.Contracts.Entity;
using AutomaticSubtitles.Service.Application.TranslationRecord.Commands;
using AutomaticSubtitles.Service.Domain.Translate;
using System.Threading.Tasks;
using System.IO;
using AutomaticSubtitles.Service.DataAccess.Model;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.DependencyInjection;
using AutomaticSubtitles.Service.Domain.Media;

namespace AutomaticSubtitles.Service.Application.TranslationRecord;

public class TranslationRecordCommandHandler
{
    private readonly ILogger<TranslationRecordCommandHandler> _logger;
    private readonly IMediaRepository _mediaRepository;
    private readonly ITranslationRecordRepository _repository;
    private readonly IServiceProvider _serviceProvider;

    public TranslationRecordCommandHandler(ITranslationRecordRepository repository, ILogger<TranslationRecordCommandHandler> logger, IServiceProvider serviceProvider,
        IMediaRepository mediaRepository)
    {
        _repository = repository;
        _logger = logger;
        _serviceProvider = serviceProvider;
        _mediaRepository = mediaRepository;
    }

    [EventHandler]
    public async Task Handle(DeleteTranslationRecordCommand command)
    {
        // 获取要删除的记录
        var records = await _repository.GetRecordsByIdsAsync(command.Ids);

        if (!records.Any())
        {
            command.Result = 0;
            return;
        }

        // 如果需要删除源文件
        if (command.DeleteSourceFile)
            foreach (var record in records)
                // 删除翻译后的字幕文件
                if (File.Exists(record.TranslatedPath))
                    File.Delete(record.TranslatedPath);

        // 删除记录
        var count = await _repository.DeleteTranslationRecordsAsync(command.Ids);
        command.Result = count;
    }

    [EventHandler]
    public async Task Handle(AddTranslationRecordCommand command)
    {
        try
        {
            // 获取媒体仓储以检查媒体ID
            // var mediaRepository = _serviceProvider.GetRequiredService<IMediaRepository>();

            // 首先检查提供的媒体ID是否存在冲突
            var mediaId = command.AutoMedia.Id;
            var existingMedia = await _mediaRepository.FindAsync(x => x.Id == mediaId);
            var originalMedia = command.AutoMedia;

            // 如果命令中的媒体与数据库中存在的媒体不是同一对象（通过路径比较）
            // 这表明可能是试图添加一个使用已存在ID的新媒体对象
            if (existingMedia != null && existingMedia.Path != originalMedia.Path)
            {
                _logger.LogWarning($"检测到媒体ID冲突，数据库中已存在ID为 {mediaId} 的媒体，路径不匹配。生成新ID...");
                // 强制生成新的媒体ID
                mediaId = await GenerateUniqueMediaId(_mediaRepository);
                originalMedia.SetId(mediaId);
            }

            // 生成记录唯一ID并检查
            var recordId = BasicsHelper.GetId();
            // 检查生成的ID是否已存在
            var existingRecord = await _repository.FindAsync(x => x.Id == recordId);
            if (existingRecord != null)
            {
                _logger.LogWarning($"生成的记录ID已存在，重新生成: {recordId}");
                recordId = BasicsHelper.GetId(); // 重新生成ID

                // 再次检查，确保新生成的ID唯一
                existingRecord = await _repository.FindAsync(x => x.Id == recordId);
                if (existingRecord != null)
                {
                    _logger.LogWarning($"再次生成的ID依然存在冲突，使用时间戳和随机数组合生成ID");
                    recordId = $"record_{DateTime.Now.Ticks}_{Guid.NewGuid():N}";
                }
            }

            // 创建翻译记录实体
            var record = new Auto_TranslationRecord(recordId)
            {
                MediaId = mediaId,
                Name = Path.GetFileName(command.TranslatedPath),
                TranslatedLanguage = command.TranslatedLanguage,
                TranslatedPath = command.TranslatedPath,
                AutoMedia = originalMedia
            };
            command.Result = await _repository.AddTranslationRecordAsync(record);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "添加翻译记录时发生未知错误");
            throw;
        }
    }

    /// <summary>
    /// 生成一个保证唯一的媒体ID
    /// </summary>
    /// <param name="mediaRepository">媒体仓储</param>
    /// <param name="maxAttempts">最大尝试次数，默认5次</param>
    /// <returns>唯一的媒体ID</returns>
    private async Task<string> GenerateUniqueMediaId(IMediaRepository mediaRepository, int retryCount = 0)
    {
        if (retryCount > 5) // 限制尝试次数，避免无限循环
        {
            _logger.LogWarning($"尝试生成唯一ID次数过多，使用更复杂的备选方案");
            // 使用多种随机源组合生成一个极不可能重复的ID
            var complexId = $"media_{DateTime.Now.Ticks}_{Guid.NewGuid():N}_{Path.GetRandomFileName().Replace(".", "")}_{Random.Shared.Next(10000, 99999)}";
            _logger.LogInformation($"生成复杂ID: {complexId}");
            return complexId;
        }

        // 生成基本ID
        var mediaId = BasicsHelper.GetId();

        // 检查ID是否已存在
        var existingMedia = await mediaRepository.FindAsync(x => x.Id == mediaId);
        if (existingMedia != null)
        {
            _logger.LogWarning($"媒体ID {mediaId} 已存在，尝试重新生成 (尝试次数: {retryCount + 1})");
            // 递归调用，重新生成
            return await GenerateUniqueMediaId(mediaRepository, retryCount + 1);
        }

        return mediaId;
    }

    // 检查媒体ID冲突并解决
    private async Task<string> EnsureUniqueMediaId(Auto_Media media, IMediaRepository mediaRepository)
    {
        _logger.LogInformation($"检查媒体ID的唯一性: {media.Id}");

        // 先检查ID是否已存在
        var existingMedia = await mediaRepository.FindAsync(x => x.Id == media.Id);
        if (existingMedia == null)
            // ID不存在，直接返回原ID
            return media.Id;

        // ID存在，检查路径是否匹配
        if (existingMedia.Path == media.Path)
        {
            _logger.LogInformation($"媒体ID {media.Id} 已存在，但路径匹配，可复用现有记录");
            return media.Id; // 路径匹配，可以重用相同ID
        }

        // ID存在且路径不匹配，需要生成新ID
        _logger.LogWarning($"检测到媒体ID冲突，数据库中已存在ID {media.Id} 的媒体，路径不匹配。生成新ID...");
        var newId = await GenerateUniqueMediaId(mediaRepository);
        _logger.LogInformation($"为媒体 {media.Name} 生成新ID: {newId}，原ID: {media.Id}");

        // 设置新ID
        media.SetId(newId);
        return newId;
    }
}